package com.yc.thread.executor;


import lombok.SneakyThrows;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 常见线程池demo
 */
public class ExecutorPoolTest {

    public static void main(String[] args) {
        ExecutorPoolTest executorPoolTest = new ExecutorPoolTest();

//        executorPoolTest.testFixPool();
//        executorPoolTest.testCachePool();
//        executorPoolTest.testSinglePool();
        executorPoolTest.testScheduledPool();
    }

    public void testFixPool() {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        for (int i=0; i<5; i++) {
            fixedThreadPool.execute(new FixPoolDemo(i));
        }
        fixedThreadPool.shutdown();
    }

    public void testCachePool() {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i=0; i<5; i++) {
            cachedThreadPool.execute(new CachePoolDemo(i));
        }
//        这里没用调用shutDown方法，这里可以发现过60秒之后，会自动释放资源。
//        cachedThreadPool.shutdown();
    }

    public void testSinglePool() {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i=0; i<5; i++) {
            singleThreadExecutor.execute(new SinglePoolDemo(i));
        }
        singleThreadExecutor.shutdown();
    }

    public void testScheduledPool() {
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
        scheduledExecutorService.scheduleAtFixedRate(new ScheduledPoolDemo(), 0, 2, TimeUnit.SECONDS);
    }


    /**
     * 固定大小的线程池，可以指定线程池的大小
     * 阻塞队列使用的是LinkedBlockingQueue，大小为整数最大值
     * 存在着耗尽系统资源的问题,需要shutdown
     */
    class FixPoolDemo implements Runnable {
        private int threadId;

        public FixPoolDemo(int threadId) {
            this.threadId = threadId;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(500L);
                System.out.println(threadId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 缓存线程池，缓存的线程默认存活60秒
     * 核心池最大为Integer.MAX_VALUE,阻塞队列使用的是SynchronousQueue
     */
    class CachePoolDemo implements Runnable {
        private int threadId;

        public CachePoolDemo(int threadId) {
            this.threadId = threadId;
        }

        @SneakyThrows
        @Override
        public void run() {
            Thread.sleep(500L);
            System.out.println(threadId);
        }
    }


    /**
     * 单个线程线程池，只有一个线程的线程池
     * 阻塞队列使用的是LinkedBlockingQueue
     * 按照先入先出的顺序执行任务
     */
    class SinglePoolDemo implements Runnable {
        private int threadId;
        public SinglePoolDemo(int threadId) {
            this.threadId = threadId;
        }
        @Override
        public void run() {
            try {
                Thread.sleep(500L);
                System.out.println(threadId);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 定时线程池，该线程池可用于周期性地去执行任务，通常用于周期性的同步数据
     * scheduleAtFixedRate:是以固定的频率去执行任务，周期是指每次执行任务成功执行之间的间隔。
     * schedultWithFixedDelay:是以固定的延时去执行任务，延时是指上一次执行成功之后和下一次开始执行的之前的时间。
     */
    class ScheduledPoolDemo implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(3000L);
                System.out.println(Thread.currentThread().getId() + "执行了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
